package hw04.grammar;

import hw04.grammar.productions.AttrList;
import hw04.grammar.productions.Command;
import hw04.grammar.productions.EDB;
import hw04.grammar.productions.Fact;
import hw04.grammar.productions.IDB;
import hw04.grammar.productions.PartialAttrList;
import hw04.grammar.productions.PartialSugoals;
import hw04.grammar.productions.Rule;
import hw04.grammar.productions.Subgoals;
import hw04.grammar.terminals.CloseParen;
import hw04.grammar.terminals.Comma;
import hw04.grammar.terminals.Constant;
import hw04.grammar.terminals.Dash;
import hw04.grammar.terminals.EvalMode;
import hw04.grammar.terminals.If;
import hw04.grammar.terminals.OpenParen;
import hw04.grammar.terminals.Period;
import hw04.grammar.terminals.QuestionMark;
import hw04.grammar.terminals.Trace;
import hw04.grammar.terminals.Variable;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class DatalogGrammar extends Grammar<Executable> {

	public Map<String, Class<? extends Terminal>> terminals;
	public Set<Class<?>> productions;

	@Override
	public Map<String, Class<? extends Terminal>> getTerminals() {
		if(terminals == null) {
			terminals = new HashMap<String, Class<? extends Terminal>>();
			terminals.put("[A-Z][a-zA-Z\\d]*", Constant.class);
			terminals.put("\\b(?!trace|evalmode)[a-z][a-zA-Z\\d]*\\b", Variable.class);
			terminals.put("\\(", OpenParen.class);
			terminals.put("\\)", CloseParen.class);
			terminals.put(",", Comma.class);
			terminals.put("\\.", Period.class);
			terminals.put("\\?", QuestionMark.class);
			terminals.put("\\-", Dash.class);
			terminals.put(":\\-", If.class);
			terminals.put("trace (on|off)\\.", Trace.class);
			terminals.put("evalmode (naive|seminaive)\\.", EvalMode.class);
		}
		return terminals;
	}
	
	@Override
	public Set<Class<?>> getProductions() {
		if(productions == null) {
			productions = new HashSet<Class<?>>();
			productions.add(PartialAttrList.class);
			productions.add(AttrList.class);
			productions.add(Rule.class);
			productions.add(EDB.class);
			productions.add(IDB.class);
			productions.add(PartialSugoals.class);
			productions.add(Subgoals.class);
			productions.add(Rule.class);
			productions.add(Fact.class);
			productions.add(Command.class);
		}
		return productions;
	}
	
}